#include "robotscripti.h"
#include "tmglobaldef.h"

TmJsEngineCtrl::TmJsEngineCtrl(QObject *parent) : QObject(parent)
{
    pr_pEngineState = NULL;
    pr_pEngineWorker = NULL;

}

void TmJsEngineCtrl::init()
{
    if( pr_pEngineWorker ){
        return;
    }
    pr_pEngineState = new TmJsEngineState(false); // main js
    pr_pEngineWorker = new TmJsEngineWorker(pr_pEngineState);
    pr_pEngineWorker->pr_bExit = false;
    pr_pEngineWorker->start();
}

void TmJsEngineCtrl::unInit()
{
    if( pr_pEngineWorker ){
        pr_pEngineWorker->pr_bExit = true;
        pr_pEngineWorker->quit();
        pr_pEngineWorker = NULL;
    }

}

void TmJsEngineCtrl::js_main_load_file(QString strFilePath)
{
    QFile file(strFilePath);
    QByteArray bArray;
    if( file.open(QIODevice::ReadWrite) ){
        bArray = file.readAll();
        file.close();
    }
    js_main_load_content(QString::fromUtf8(bArray));
}

void TmJsEngineCtrl::js_main_load_content(QString strJsContent)
{
    if( pr_pEngineWorker ){
        pr_pEngineWorker->load_js_start(strJsContent);
    }
}

void TmJsEngineCtrl::js_main_stop()
{
    if( pr_pEngineState ){
        pr_pEngineState->setStopped(true);
    }
}

bool TmJsEngineCtrl::js_main_isPlaying()
{
    if( pr_pEngineState ){
        return !pr_pEngineState->getStopped();
    }
    return false;
}

// ---------------------------------------- //

TmJsEngineWorker::TmJsEngineWorker(TmJsEngineState *pWork, QObject *parent)
{
    pr_bExit = false;
    pr_bStartLoad = false;
    pr_pEngine = NULL;
    pr_pWork = pWork;
}

void TmJsEngineWorker::run()
{
    pr_pEngine = new QScriptEngine();
    QScriptValue valScript = pr_pEngine->newQObject(g_pSerialTh);
    pr_pEngine->globalObject().setProperty("Script", valScript);

    QScriptValue valJson = pr_pEngine->newQObject(g_pJsonEngTh);
    pr_pEngine->globalObject().setProperty("Json", valJson);

    QScriptValue valMotor = pr_pEngine->newQObject(g_pSerialTh);
    pr_pEngine->globalObject().setProperty("Motor", valMotor);

    QScriptValue valAudio = pr_pEngine->newQObject(g_pAudioSender);
    pr_pEngine->globalObject().setProperty("Audio", valAudio);

//    QScriptValue valConfig = pr_pEngine->newQObject(NULL);
//    pr_pEngine->globalObject().setProperty("Audio", valAudio);


    QScriptValue val2 = pr_pEngine->newQObject(pr_pWork);
    pr_pEngine->globalObject().setProperty("jsState", val2);

    while(true){
        if( pr_bExit ){
            break;
        }
        if( !pr_bStartLoad ){
            QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
            msleep(100);
            if( pr_bExit ){
                break;
            }
            continue;
        }
        pr_bStartLoad = false;
        pr_pWork->setFrameID(0);
        // 1.
        QScriptValue valret = pr_pEngine->evaluate(pr_strJsContent);
        if( valret.isError() ){
            QScriptSyntaxCheckResult retCheck = pr_pEngine->checkSyntax(pr_strJsContent);
            QString strRet = QString("[%1:%2] %3").arg(retCheck.errorLineNumber()).arg(retCheck.errorColumnNumber()).arg(retCheck.errorMessage());
            qDebug()<<"[JS] JsEngine load error!"<<strRet;
            continue;
        }
        // 2.
        QScriptValue func_loop = pr_pEngine->globalObject().property("jsLoop");
        if( !func_loop.isValid() || !func_loop.isFunction() ){
            pr_pWork->reset();
            qDebug()<<"[JS] JsEngine jsLoop Functions is unvalied!";
            continue;
        }
        pr_pWork->setStopped(false); // start
        int nLastFrameID = 0;
        while( !pr_pWork->getStopped() ){
            nLastFrameID = pr_pWork->getFrameID();
            func_loop.call();
            if( nLastFrameID == pr_pWork->getFrameID() ){
                pr_pWork->incFrameID();
            }
            msleep(pr_pWork->getFrameDelay());
        }
        pr_func_event = QScriptValue(); // reset event
        if( g_pAudioSender ){
            g_pAudioSender->TtsStop();
            g_pAudioSender->MediaStop();
        }
    }
}

void TmJsEngineWorker::load_js_start(QString strJsContent)
{
    pr_strJsContent = strJsContent;
    pr_bStartLoad = true;
    pr_pWork->setStopped(true);
}


void TmJsEngineWorker::msg_js_event(QString event, QString val)
{
    if( pr_func_event.isValid() && pr_func_event.isFunction() ){
        QScriptValueList valList;
        valList << QScriptValue(event)<<QScriptValue(val);
        pr_func_event.call(QScriptValue(), valList);
    }
}

TmJsEngineState::TmJsEngineState(bool bIsModule, QObject *parent) : QObject(parent)
{
    pr_bStopped = true;
    pr_nFrameDelay = 100;
    pr_nFrameID = 0;
    pr_bIsModule = bIsModule;
}

void TmJsEngineState::incFrameID()
{
    pr_nFrameID += 1;
}

void TmJsEngineState::reset()
{
    pr_nFrameID = 0;
    pr_bStopped = true;
}

int TmJsEngineState::getFrameID() const
{
    return pr_nFrameID;
}

void TmJsEngineState::setFrameID(int nFrameID)
{
    pr_nFrameID = nFrameID;
}

int TmJsEngineState::getFrameDelay() const
{
    return pr_nFrameDelay;
}

void TmJsEngineState::setFrameDelay(int nFrameDelay)
{
    pr_nFrameDelay = nFrameDelay;
}

bool TmJsEngineState::getStopped() const
{
    return pr_bStopped;
}

void TmJsEngineState::setStopped(bool bStopped)
{
    pr_bStopped = bStopped;
}

bool TmJsEngineState::getIsModule() const
{
    return pr_bIsModule;
}

//-------------------------------------//

RobotScriptI::RobotScriptI()
{

}
